package SSF.App.DDoS;

import SSF.OS.*;
import SSF.Net.*;
import SSF.OS.NetFlow.BytesUtil;
import SSF.Util.Streams.*;
import com.renesys.raceway.DML.*;
import com.renesys.raceway.SSF.*;
import java.text.*;
import java.util.LinkedList;

/**
 * Used to monitor the process of DDoS hosts, generating data used in
 * animation (demo).
 * @author Yougu.
 */
public class DDoSMonitor implements ProtocolMonitor {

    public static final String STREAM_TYPE = "DDoSMonitor";

    private java.text.DecimalFormat fm = new DecimalFormat();

    protected DDoSSessionRand owner=null;

    private StreamInterface S;
    private int hostcode;
    private int typeCode;
    private double invfreq;

    public boolean DEBUG;

    /** configure the Monitor. The supported DML attributes are:
     * <PRE>
     *   monitor [
     *     use SSF.OS.DDoS.DDoSMonitor
     *     debug           %S   # print verbose diagnostics, true/false
     *   ]
     * </PRE>
     */
    public void config(ProtocolSession ownerProtocol, Configuration cfg) throws configException {
	try {
	    owner = (DDoSSessionRand)ownerProtocol;
	} catch (ClassCastException cce) {
	    throw new 
		configException("DDoSSessionRand not found for the monitor.");
	}
	invfreq = 1.0/Net.frequency;

	String str = (String)cfg.findSingle("debug");
	if (str != null)
	    DEBUG = Boolean.valueOf(str).booleanValue();

	// format time output
	fm.setMinimumFractionDigits(3);
	fm.setMaximumFractionDigits(3);
   
	if (DEBUG)
	    System.out.println("Configuring DDoSMonitor... Host:"+((Host)(owner.inGraph())).nhi);
    }

    /** called by SSF.OS.DDoS.DDoSSessionRand.init()
     */
    public void init() 
    {

	ProbeSession P = null;

	if (DEBUG)
	    System.out.println("init DDoSMonitor.");
	
	try {
	    P = (ProbeSession)(owner.inGraph().SessionForName("probe"));
	    S = P.getRecorder();
	    hostcode = P.getHostCode();
	    typeCode = S.getRecordTypeCode(STREAM_TYPE);
	} catch (ProtocolException pex) {
	    System.err.println(" Can't configure DDoSMonitor: no ProbeSession registered in host");
	    System.err.println(pex.getMessage());
	    System.exit(1);
	}
    }

    protected void sendRecord(DDoSMessage msg) {
	double time = invfreq*owner.inGraph().now();

	byte[] record = new byte[2];

	//record[0] = new Integer(msg.action).byteValue();
	record[0] = (byte)msg.action;
	record[1] = (byte)owner.level;
	if (DEBUG) {
	    System.out.println("DDoSMonitor: " + fm.format(time)+" "+
			       recordToString(record, 0));
	}

	if (S==null) {
	    System.err.println("DDoSMonitor: StreamInterface S NOT initialized.\n");
	    return;
	}

	S.send(typeCode, hostcode, time, record, 0, record.length);

    }

    public static String recordToString(byte[] bytes, int offset)
    {
	String cmd, level;
	int L;

	switch (bytes[offset]) {
	case DDoSMessage.HIJACK:
	    cmd ="hijacked"; break;
	case DDoSMessage.INSTALL:
	    cmd ="installed."; break;
	case DDoSMessage.START_ATTACK:
	    cmd ="start attack";break;
	case DDoSMessage.END_ATTACK:
	    cmd ="end attack"; break;
	case DDoSMessage.ACK:
	    cmd ="ack"; break;
	case DDoSMessage.UNINSTALL:
	    cmd ="uninstall";break;
	default:
	    cmd = null;
	}

	L = (int)bytes[offset+1];
	switch (L) {
	case DDoSSessionRand.ATTACKER:
	    level = "attacker"; break;
	case DDoSSessionRand.MASTER:
	    level = "master"; break;
	case DDoSSessionRand.AGENT:
	    level = "agent"; break;
	default:
	    level = null;
	}
	
	return level+" "+cmd;
    }
    public void receive(ProtocolMessage msg, ProtocolSession fromSession, ProtocolSession toSession) 
    {
	DDoSMessage dmsg=null;

	try {
	    dmsg = (DDoSMessage)msg;
	} catch (ClassCastException cce) {
	    System.err.println("Non DDoSMessage received in DDoSMonitor.\n");
	    return;
	}

	sendRecord(dmsg);
    }
}


